package com.tiger.easyrpc.core.spring;

import com.tiger.easyrpc.common.URLUtils;
import com.tiger.easyrpc.core.EasyRpcManager;
import com.tiger.easyrpc.core.annotation.Exporter;
import com.tiger.easyrpc.core.cache.server.ExportServiceManager;
import com.tiger.easyrpc.core.config.ProviderConfig;
import com.tiger.easyrpc.core.metadata.ExporterMetadata;
import com.tiger.easyrpc.core.metadata.MetadataManager;
import com.tiger.easyrpc.core.util.BeanDefinitionRegistryUtils;
import com.tiger.easyrpc.core.util.PathResolverUtils;
import com.tiger.easyrpc.registry.RegistryManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.StringUtils;

import java.lang.reflect.Type;
import java.net.SocketException;
import java.util.List;

import static com.tiger.easyrpc.common.EasyrpcConstant.COMMON_SYMBOL_MH;
import static com.tiger.easyrpc.common.EasyrpcConstant.EMPTY_STR;

/**
 * 找到标有ExporterScan注解的类，获取注解值，加载指定包中带有Exporter的类放入Set中
 */
public class ExporterResolver implements BeanDefinitionRegistryPostProcessor, ApplicationListener<ContextRefreshedEvent> {
    private Logger logger = LoggerFactory.getLogger(ExporterResolver.class);
    public ExporterResolver(){
    }
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }


    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        resolver();
        for(Class c:ExportServiceManager.exporterClass){
            BeanDefinitionRegistryUtils.regist(beanDefinitionRegistry,c);
        }
    }

    private void resolver(){
        String scanPath = EasyRpcManager.getInstance().getServiceScanPath();
        List<Class> classes = PathResolverUtils.resolverByAnnotation(scanPath, Exporter.class);
        ExportServiceManager.exporterClass.addAll(classes);
    }

    /**
     * 保存Exporter元数据
     * @param annotation Exporter注解
     * @param aClass 被注解的类
     */
    private void addMetadata(Exporter annotation,Class aClass){
        ExporterMetadata metadata = new ExporterMetadata();
        metadata.setGroup(annotation.group());
        metadata.setVersion(annotation.version());
        metadata.setFailbackClass(annotation.failbackClass());
        metadata.setServiceName(annotation.serviceName());
        MetadataManager.getInstance().setExporterMetadata(aClass.getName(),metadata);
    }

    /**
     * 获取服务全名称
     * @param aClass 服务类
     * @return
     */
    private String getFullServiceName(Class aClass){
        //获取接口
        Type[] genericInterfaces = aClass.getGenericInterfaces();
        if(genericInterfaces.length == 0){
            logger.info("服务类{}需要实现一个服务接口",aClass.getName());
            throw new RuntimeException("{}服务类需要实现接口！");
        }
        Exporter annotation = (Exporter) aClass.getAnnotation(Exporter.class);
        String group = annotation.group();
        String version = annotation.version();
        String serviceName = annotation.serviceName();
        addMetadata(annotation,aClass);
        ProviderConfig providerConfig = EasyRpcManager.getInstance().getProviderConfig();
        Class serviceInterface = (Class)genericInterfaces[0];
        if(StringUtils.isEmpty(version)){
            version = providerConfig.getVersion() == null ? EMPTY_STR : providerConfig.getVersion();
        }
        if(StringUtils.isEmpty(group)){
            group = providerConfig.getGroup() == null ? EMPTY_STR : providerConfig.getGroup();
        }
        if(StringUtils.isEmpty(serviceName)){
            serviceName = providerConfig.getServiceName();
        }
        if(StringUtils.isEmpty(serviceName)){
            serviceName = serviceInterface.getName();
        }
        return serviceName+
                COMMON_SYMBOL_MH+version+COMMON_SYMBOL_MH+group;
    }

    private void addService(Class aClass){
        try {
            String serviceName = getFullServiceName(aClass);
            if(EasyRpcManager.getInstance().isEnableRegistry()){
                //注册中心发布
                RegistryManager.getInstance().regist(serviceName,URLUtils.getLocalServerUrlAndPort());
            }
            ExportServiceManager.services.put(serviceName,aClass);
        }  catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (SocketException e) {
            throw new RuntimeException("获取本机地址失败！",e);
        }

    }

    /**
     * 当接收到服务启动通知，发布服务并保存服务类信息
     * @param contextRefreshedEvent
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = applicationContext.getBean(beanDefinitionName);
            Exporter annotation = bean.getClass().getAnnotation(Exporter.class);
            if(annotation == null){
                continue;
            }
            this.addService(bean.getClass());
        }
        if(EasyRpcManager.getInstance().isEnableRegistry()){
            //服务启动，发布服务注册事件，刷新客户端本地缓存
            RegistryManager.getInstance().publishUrlChange();
        }
    }
}
